﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.Triangulate.QuadEdge;

namespace NetTopologySuite.Triangulate
{
	public class DelaunayTriangulationBuilder
	{
		public static CoordinateList ExtractUniqueCoordinates(IGeometry geom)
		{
			if (geom == null)
			{
				return new CoordinateList();
			}
			return DelaunayTriangulationBuilder.Unique(geom.Coordinates);
		}

		public static CoordinateList Unique(Coordinate[] coords)
		{
			Coordinate[] array = CoordinateArrays.CopyDeep(coords);
			Array.Sort<Coordinate>(array);
			return new CoordinateList(array, false);
		}

		public static IList<Vertex> ToVertices(ICollection<Coordinate> coords)
		{
			List<Vertex> list = new List<Vertex>();
			foreach (Coordinate p in coords)
			{
				list.Add(new Vertex(p));
			}
			return list;
		}

		public static Envelope Envelope(ICollection<Coordinate> coords)
		{
			Envelope envelope = new Envelope();
			foreach (Coordinate p in coords)
			{
				envelope.ExpandToInclude(p);
			}
			return envelope;
		}

		public void SetSites(IGeometry geom)
		{
			this._siteCoords = DelaunayTriangulationBuilder.ExtractUniqueCoordinates(geom);
		}

		public void SetSites(ICollection<Coordinate> coords)
		{
			this._siteCoords = DelaunayTriangulationBuilder.Unique(CoordinateArrays.ToCoordinateArray(coords));
		}

		public double Tolerance
		{
			set
			{
				this._tolerance = value;
			}
		}

		private void Create()
		{
			if (this._subdiv != null)
			{
				return;
			}
			Envelope env = DelaunayTriangulationBuilder.Envelope(this._siteCoords);
			IList<Vertex> vertices = DelaunayTriangulationBuilder.ToVertices(this._siteCoords);
			this._subdiv = new QuadEdgeSubdivision(env, this._tolerance);
			new IncrementalDelaunayTriangulator(this._subdiv).InsertSites(vertices);
		}

		public QuadEdgeSubdivision GetSubdivision()
		{
			this.Create();
			return this._subdiv;
		}

		public IMultiLineString GetEdges(IGeometryFactory geomFact)
		{
			this.Create();
			return this._subdiv.GetEdges(geomFact);
		}

		public IGeometryCollection GetTriangles(IGeometryFactory geomFact)
		{
			this.Create();
			return this._subdiv.GetTriangles(geomFact);
		}

		private ICollection<Coordinate> _siteCoords;

		private double _tolerance;

		private QuadEdgeSubdivision _subdiv;
	}
}
